﻿using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using CookComputing.XmlRpc;
using BlogML.Xml;
using BlogML;
using CodeSane.MetaWeblog.Api;
using System.Xml.Linq;
using System.Web;
using HtmlAgilityPack;

//http://metaweblogtoblogml.codeplex.com/
namespace SharpLogic.GeeksWithBlogsToBlogML
{
    public class GeeksWithBlogsToBlogMLConverter {
        
        #region Settings
        
        /// <summary>
        /// Location for BlogML XML file to be placed (will be named [blogid].xml)
        /// </summary>
        string _outPath= @"C:\Blogs";

        /// <summary>
        /// App Key - Which GWB dont need
        /// </summary>
        string _appKey = "";

        /// <summary>
        /// Url to GWB home page
        /// </summary>
        string _blogUrl = "http://geekswithblogs.net/<your user name>";

        /// <summary>
        /// Meta blog API url
        /// </summary>
        string _metaApiUrl = "/services/metablogapi.aspx";

        /// <summary>
        /// This is the base url for your images folder in Orchard - to replace the existing image url in the html markup
        /// I created a folder called migrated
        /// Note: You will have to upload the images into Orchard your self!
        /// Easiest way is to zip all the images and upload that - let Orchard do the work!
        /// </summary>
        string _orchardMediaFolderUrl = "<your new blog url>/Media/Default/Migrated/";

        /// <summary>
        /// GWB username
        /// </summary>
        string _gwbUserName = "<your gwb username>";

        /// <summary>
        /// GWB Password
        /// </summary>
        string _gwbPassword = "<your gwb password>";

        /// <summary>
        /// Number of recent posts to get
        /// </summary>
        int _numOfPostsToGet = 15;

        #endregion

        ICSMetaWeblog _proxy = null;

        public GeeksWithBlogsToBlogMLConverter()
        {
            _metaApiUrl = _blogUrl + _metaApiUrl;

            _proxy = XmlRpcProxyGen.Create<ICSMetaWeblog>();
            _proxy.Url = _metaApiUrl;
        }

        public void ExportAllBlogs()
        {
            var blogs = _proxy.getUsersBlogs(_appKey, _gwbUserName, _gwbPassword);

            foreach (BlogInfo blog in blogs)
            {
                BlogMLBlog xblog = new BlogMLBlog();
                xblog.Title = blog.blogName;
                xblog.RootUrl = blog.url;

                IEnumerable<BlogMLCategory> categories;
                categories = GetCategories(blog);
                xblog.Categories.AddRange(categories);

                xblog.Posts.AddRange(GetPosts(blog,categories));

                using (StreamWriter writer = File.CreateText(Path.Combine(_outPath, blog.blogid + ".xml")))
                {
                    BlogMLSerializer.Serialize(writer, xblog);
                }
            }
        }

        private IEnumerable<BlogMLPost> GetPosts(BlogInfo blog,IEnumerable<BlogMLCategory> categories)
        {
            var posts = from p in _proxy.getRecentPosts(blog.blogid, _gwbUserName, _gwbPassword, _numOfPostsToGet)
                        select BuildPost(p, categories);
            return posts;
        }

        private BlogMLPost BuildPost(Post p, IEnumerable<BlogMLCategory> categories)
        {
            BlogMLPost post = new BlogMLPost()
            {
                PostType=BlogPostTypes.Normal,
                Title = p.title,
                Content = new BlogMLContent()
                    {
                        Text = p.description,
                    },
                DateCreated = p.dateCreated,
                DateModified = DateTime.Today,
                ID = p.postid.ToString()
                
            };

            // SC: Add Comemnts
            var comments = GetCommentsForPost(p);
            if (comments != null) {
                foreach (var comment in comments) {
                    post.Comments.Add(comment);
                }
            }
            
            // SC: Add categories
            if (p.categories != null) {
                foreach (var cat in p.categories) {
                    var c2 = categories.Single(c => c.Description == cat);
                    post.Categories.Add(c2.ID);
                }
            }

            // SC: Download images and update path
            DownloadPostImages(post);
            
            return post;
        }

        /// <summary>
        /// Get the comments for the post
        /// </summary>
        IEnumerable<BlogMLComment> GetCommentsForPost(Post post) {
            string commentsUrl = _blogUrl + "/Comments/commentRss/" + post.postid.ToString() + ".aspx";

            XNamespace dc = "http://purl.org/dc/elements/1.1/";
            XDocument doc = XDocument.Load(commentsUrl);

            var comments = from d in doc.Descendants("item")
                           select new BlogMLComment {
                               DateCreated = DateTime.Parse(d.Element("pubDate").Value),
                               UserName = d.Element(dc + "creator").Value,
                               Title = d.Element("title").Value,
                               Content = new BlogMLContent { Text = d.Element("description").Value }
                           };

            return comments ?? null;
        }

        private IEnumerable<BlogMLCategory> GetCategories(BlogInfo blog)
        {
            var cats = _proxy.getCategories(blog.blogid, _gwbUserName, _gwbPassword);

            var categories = from c in _proxy.getCategories(blog.blogid, _gwbUserName, _gwbPassword)
                             select new BlogMLCategory() { ID = c.categoryid, Title = c.title, Description = c.description, Approved=true };
            return categories;                      
        }

        /// <summary>
        /// Download images from the post, store them and update the blog html to reflect new url
        /// </summary>
        /// <param name="post"></param>
        private void DownloadPostImages(BlogMLPost post) {
            
            string savePath = _outPath + "\\images\\Migrated\\";
            if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);

            try {
                var doc = new HtmlDocument();
                doc.LoadHtml(post.Content.Text);

                var imageUrls = doc.DocumentNode.Descendants("img")
                    .Select(e => e.GetAttributeValue("src", null))
                    .Where(s => !String.IsNullOrEmpty(s));

                foreach (HtmlNode img in doc.DocumentNode.SelectNodes("//img[@src]")) {
                    try {
                        HtmlAttribute att = img.Attributes["src"];
                        // Get File Name
                        string fileName = Path.GetFileName(att.Value);

                        // Download the image...
                        DownloadImage.DownloadAndSave(att.Value, savePath + fileName, System.Drawing.Imaging.ImageFormat.Jpeg);

                        // Update image src attribute
                        att.Value = _orchardMediaFolderUrl + fileName;
                    }
                    catch { }
                }

                post.Content.Text = doc.DocumentNode.OuterHtml;
            }
            catch (Exception) {
                
            }
        }
    }
}
